home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb.new / sprite / kgdb / sun4_kgdb_remote.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-30  |  38.4 KB  |  1,535 lines

  1. /* 
  2.  * kgdb_remote_sun4.c --
  3.  *
  4.  *    
  5.  *
  6.  * Copyright 1991 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that this copyright
  10.  * notice appears in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.5 91/02/09 13:24:44 ouster Exp $ SPRITE (Berkeley)";
  18.  
  19. #include <stdio.h>
  20. #include <sprite.h>
  21. #include <signal.h>
  22. #include <sys/types.h>
  23. #include <sys/file.h>
  24. #include <sys/wait.h>
  25. #include <errno.h>
  26. #include "kernel/machTypes.h"
  27.  
  28. #include "defs.h"
  29. #include "param.h"
  30. #include "frame.h"
  31. #include "inferior.h"
  32. #include "value.h"
  33. #include "expression.h"
  34. #include "target.h"
  35. #include "wait.h"
  36. #include "terminal.h"
  37. #include "sprite.h"
  38. #include "kernel/sun4.md/vmSunConst.h"
  39. #include "kernel/sun4.md/machConst.h"
  40. #include "kernel/sun4.md/dbg.h"
  41.  
  42. extern struct value *call_function_by_hand();
  43. extern void start_remote ();
  44.  
  45. extern struct target_ops remote_ops;    /* Forward decl */
  46.  
  47.  
  48. /*
  49.  * Hostname of attached remote hosts.  Error otherwise.
  50.  */
  51.  
  52. char *hostName;
  53.  
  54. /*
  55.  * Useful macros
  56.  * ERROR_NO_ATTACHED_HOST - Remote an error and abort if no host is
  57.  *                currently attached.
  58.  * MARK_DISCONNECTED - Mark a host a disconnected and free up state.
  59.  */
  60.  
  61. #define ERROR_NO_ATTACHED_HOST \
  62.     if (!hostName) error("No machine attached.");
  63.  
  64. #define MARK_DISCONNECTED  {     \
  65.     initialized = 0;          \
  66.     inferior_pid = 0;        \
  67.     hostName = (char *) 0;     \
  68.     free(dataCache);      \
  69.     free(cacheInfo);      \
  70.     }
  71.  
  72.  
  73. static    int    initialized = 0; /* Set to true when remote connection is
  74.                   * initialized. */
  75.  
  76. /*
  77.  * Table mapping kernel exceptions into Unix signals.  
  78.  */
  79.  
  80. struct sig_mapping_struct {
  81.     char     *sig_name;    /* Print string for signal. */
  82.     int     dbgSig;     /* Boolean - A signal used by the debugger. */
  83.     int     unixSignal;     /* Unix signal equalient. */
  84. } sig_mapping[] =  {
  85. /* 0 */ { "Reset Trap", 0, SIGQUIT },
  86. /* 1 */ { "Instruction Fault", 0, SIGSEGV },
  87. /* 2 */ { "Illegal Instruction Fault", 0, SIGILL },
  88. /* 3 */ { "Privilege Instruction Fault", 0, SIGILL },
  89. /* 4 */ { "FPU Disabled Fault", 0, SIGFPE },
  90. /* 5 */ { "Window Overflow Fault", 0, SIGBUS },
  91. /* 6 */ { "Window Underflow Fault", 0, SIGBUS },
  92. /* 7 */ { "Memory Address Fault", 0, SIGSEGV },
  93. /* 8 */ { "FPU Exception Fault", 0, SIGFPE },
  94. /* 9 */ { "Data Fault",  0, SIGSEGV },
  95. /* 10 */ { "Tag Overflow Trap", 0, SIGSEGV },
  96. /* 11 */ { "Unknown Trap 11",  0, SIGSEGV },
  97. /* 12 */ { "Unknown Trap 12",  0, SIGSEGV },
  98. /* 13 */ { "Unknown Trap 13",  0, SIGSEGV },
  99. /* 14 */ { "Unknown Trap 14",  0, SIGSEGV },
  100. /* 15 */ { "Unknown Trap 15",  0, SIGSEGV },
  101. /* 16 */ { "Interrupt Trap",  0, SIGINT },
  102. /* 17 */ { "Level 1 Interrupt", 0, SIGINT },
  103. /* 18 */ { "Level 2 Interrupt", 0, SIGINT },
  104. /* 19 */ { "Level 3 Interrupt", 0, SIGINT },
  105. /* 20 */ { "Level 4 Interrupt", 0, SIGINT },
  106. /* 21 */ { "Level 5 Interrupt", 0, SIGINT },
  107. /* 22 */ { "Level 6 Interrupt", 0, SIGINT },
  108. /* 23 */ { "Level 7 Interrupt", 0, SIGINT },
  109. /* 24 */ { "Level 8 Interrupt", 0, SIGINT },
  110. /* 25 */ { "Level 9 Interrupt", 0, SIGINT },
  111. /* 26 */ { "Level 10 Interrupt", 0, SIGINT },
  112. /* 27 */ { "Level 11 Interrupt", 0, SIGINT },
  113. /* 28 */ { "Level 12 Interrupt", 0, SIGINT },
  114. /* 29 */ { "Level 13 Interrupt", 0, SIGINT },
  115. /* 30 */ { "Level 14 Interrupt", 0, SIGINT },
  116. /* 31 */ { "Level 15 Interrupt", 0, SIGINT },
  117. /* 32 */ { "Breakpoint Trap",  1, SIGTRAP },
  118. /* 33 */ { "Unknown Trap",  0, SIGSEGV },
  119. /* 34 */ { "UNKNOWN EXCEPTION", 0, SIGSEGV },
  120. };
  121.  
  122. #define    NUM_SIG_MAPS    (sizeof(sig_mapping)/sizeof(sig_mapping[0]))
  123.  
  124.  
  125.  
  126. #define    PBUFSIZ    1024
  127.  
  128. /* Maximum number of bytes to read/write at once.  The value here
  129.    is chosen to fill up a packet (the headers account for the 32).  */
  130. #define MAXBUFBYTES ((PBUFSIZ-32)/2)
  131.  
  132.  
  133. /*
  134.  *----------------------------------------------------------------------
  135.  *
  136.  * Regnum_to_index --
  137.  *
  138.  *    Function mapping a gdb register number into an index.
  139.  *
  140.  * Results:
  141.  *    Index to Mach_State structure when treated as an array on ints.
  142.  *
  143.  * Side effects:
  144.  *    None.
  145.  *
  146.  *----------------------------------------------------------------------
  147.  */
  148. static int 
  149. Regnum_to_index(r) 
  150.     int    r;
  151. #define    O(f)    ((int)&(((Mach_RegState *) 0)->f)/sizeof(int))
  152.   if (r < 8) return O(globals[r]);
  153.   if (r < 16) return  O(ins[r-8]);
  154.   if (r < 32) return (r - 16);
  155.   if (r == Y_REGNUM) return O(y);
  156.   if (r == PS_REGNUM) return O(curPsr);
  157.   if (r == PC_REGNUM) return O(pc);
  158.   if (r == NPC_REGNUM) return O(nextPc);
  159.   return -1;
  160. #undef O
  161. };
  162. static int lastPid = -1;    /* Process ID of process being examined. -1
  163.                  * means process causing trap. */
  164.  
  165. /*
  166.  * The following variables are sued when using the core memory interface
  167.  * rather than active ethernet debugging.
  168.  */
  169. static int remoteCoreChan = -1;    /* Open file descriptor of core file. -1 
  170.                  * means no file open. */
  171. static char *remoteCoreFile;    /* Malloced name of core file. */
  172. static int remoteOffset;    /* Offset used to convert addresses to 
  173.                  * offsets into core file. */
  174. static StopInfo    remoteStopInfo;    /* Current Dbg_StopInfo from core file. */
  175. static Dbg_DumpBounds remoteBounds;  /* Dump bounds from core file. */
  176.  
  177. /*
  178.  * IN_CORE_FILE - Returns TRUE if address is in the corefile.
  179.  */
  180. #define    IN_CORE_FILE(addr) ((addr) >= (CORE_ADDR) remoteBounds.kernelCodeStart\
  181.       && ((addr) < (CORE_ADDR) remoteBounds.fileCacheStart + \
  182.                           remoteBounds.fileCacheSize))
  183.  
  184. /*
  185.  *----------------------------------------------------------------------
  186.  *
  187.  * remote_core_file_command --
  188.  *
  189.  *    kgdb.sun4 core_file command.
  190.  *
  191.  * Results:
  192.  *    None.
  193.  *
  194.  * Side effects:
  195.  *    None.
  196.  *
  197.  *----------------------------------------------------------------------
  198.  */
  199.  
  200. void
  201. remote_core_file_command (filename, from_tty)
  202.      char *filename;
  203.      int from_tty;
  204. {
  205.   /* Discard all vestiges of any previous core file
  206.      and mark data and stack spaces as empty.  */
  207.  
  208.   if (remoteCoreFile)
  209.     free (remoteCoreFile);
  210.   remoteCoreFile = 0;
  211.  
  212.   if (remoteCoreChan >= 0)
  213.     close (remoteCoreChan);
  214.   remoteCoreChan = -1;
  215.   if (filename == 0) {
  216.     printf ("Corefile cleared.\n");
  217.     return;
  218.   }
  219.  
  220.   filename = tilde_expand (filename);
  221.   make_cleanup (free, filename);
  222.  
  223.   remoteCoreChan = open (filename, O_RDONLY, 0);
  224.   if (remoteCoreChan < 0)
  225.     perror_with_name (filename);
  226.  
  227.   {
  228.     /*
  229.      * Read the StopInfo and bounds and start the debugging session.
  230.      */
  231.     int val;
  232.     val = myread (remoteCoreChan, &remoteStopInfo, sizeof remoteStopInfo);
  233.     if (val < 0)
  234.       perror_with_name (filename);
  235.     val = myread (remoteCoreChan, &remoteBounds, sizeof remoteBounds);
  236.     if (val < 0)
  237.       perror_with_name (filename);
  238.     remote_debugging = 1;
  239.     remoteOffset = remoteBounds.kernelCodeStart - sizeof(remoteStopInfo) -
  240.             sizeof(remoteBounds);
  241.     start_remote();
  242.   }
  243. }
  244.  
  245. /* Open a connection to a remote debugger.
  246.    NAME is the filename used for communication.  */
  247.  
  248. void
  249. remote_open (name, from_tty)
  250.      char *name;
  251.      int from_tty;
  252. {
  253.   if (remoteCoreChan >= 0) {
  254.       error("Can't attach a machine when using a corefile\n");
  255.       return;
  256.   }
  257.  
  258.   if (name == 0)
  259.     error (
  260. "To open a remote debug connection, you need to specify what host\n\
  261. machine is attached to the remote system (e.g. allspice).");
  262.  
  263.   hostName = savestring(name,strlen(name));
  264.   if (from_tty)
  265.     printf ("Remote debugging using %s\n", name);
  266.   push_target (&remote_ops);    /* Switch to using remote target now */
  267. }
  268.  
  269. char *
  270. remote_version()
  271. {
  272.   static char    version[1024];
  273.  
  274.   ERROR_NO_ATTACHED_HOST;
  275.   Kdbx_Trace(DBG_GET_VERSION_STRING, 0, version, 1024);
  276.   return version;
  277. }
  278.  
  279.  
  280.  
  281. /* Tell the remote machine to resume.  */
  282.  
  283. int     step_addr, step_addr_contents[2];
  284.  
  285. int
  286. remote_resume (step, signal)
  287.      int step, signal;
  288. {
  289.  
  290.   ERROR_NO_ATTACHED_HOST;
  291.   step_addr = -2;
  292.   if (step) {
  293.          static char break_insn[] = BREAKPOINT;
  294.          step_addr = read_register(NPC_REGNUM);
  295.          if ((remote_read_bytes(step_addr,step_addr_contents,8) != 0) ||
  296.          (remote_write_bytes(step_addr,break_insn, 4) != 0) ||
  297.          (remote_write_bytes(step_addr+4,break_insn, 4) != 0)) {
  298.          error("Can't set single step breakpoint at 0x%x\n", step_addr);
  299.       }
  300.  
  301.   }
  302.   if (Kdbx_Trace( DBG_CONTINUE, 0, 0, sizeof(int)) < 0) {
  303.         error("error trying to continue process\n");
  304.   }
  305.  
  306. }
  307.  
  308. /* Wait until the remote machine stops, then return,
  309.    storing status in STATUS just as `wait' would.  */
  310.  
  311. int
  312. remote_wait (status)
  313.      WAITTYPE *status;
  314. {
  315.     StopInfo    stopInfo;
  316.     int        trap;
  317.     int    text_size;
  318.     extern CORE_ADDR text_start, text_end;
  319.     if (remoteCoreChan >= 0) {
  320.     /*
  321.      * Debugging using core file, just set text_{start, end} and
  322.      * returned stopped signal.
  323.      */
  324.     status->w_status = 0;
  325.     status->w_stopval = WSTOPPED;
  326.     trap = DBG_CVT_MACH_TRAP(remoteStopInfo.trapType);
  327.     status->w_stopsig = sig_mapping[trap].unixSignal;
  328.     if ((lastPid == -1) && !sig_mapping[trap].dbgSig) { 
  329.         printf("Kernel returns with signal (%d) %s\n",
  330.             remoteStopInfo.trapType,
  331.             sig_mapping[trap].sig_name);
  332.     }
  333.     text_start = remoteBounds.kernelCodeStart;
  334.     text_end = remoteBounds.kernelCodeStart + remoteBounds.kernelCodeSize;
  335.     return status->w_stopsig;
  336.     }
  337.     ERROR_NO_ATTACHED_HOST;
  338.  
  339.     if (Kdbx_Trace(DBG_GET_STOP_INFO, (char *) 0, (char *)&stopInfo,
  340.                sizeof(stopInfo)) != 0) {
  341.     error("Can't get stop info\n");
  342.     }
  343.  
  344.     if (stopInfo.regs.pc == step_addr ||
  345.     stopInfo.regs.pc == step_addr+4) {
  346.          if (remote_write_bytes(step_addr,step_addr_contents, 8) != 0) 
  347.          error("Can't restore single step address\n");
  348.     }
  349.     status->w_status = 0;
  350.     status->w_stopval = WSTOPPED;
  351.  
  352.     trap = DBG_CVT_MACH_TRAP(stopInfo.trapType);
  353.     status->w_stopsig = sig_mapping[trap].unixSignal;
  354.     if ((lastPid != -1) && !sig_mapping[trap].dbgSig) { 
  355.     printf("Kernel returns with signal (%d) %s\n",stopInfo.trapType,
  356.         sig_mapping[trap].sig_name);
  357.     }
  358.  
  359.     text_size = text_end - text_start;
  360.     text_size &= ~(8*1024-1);
  361.     text_start = stopInfo.codeStart - 8*1024;
  362.     text_end = text_start+text_size;
  363.     return status->w_stopsig;
  364. }
  365.  
  366. /* Read the remote registers into the block REGS.  */
  367. #define FIRST_LOCAL_REGNUM    16
  368. void
  369. remote_fetch_registers (regs)
  370.      char *regs;
  371. {
  372.   StopInfo    stopInfo;
  373.   if (remoteCoreChan >= 0) {
  374.  
  375.       bcopy(remoteStopInfo.regs.globals,regs,4*8);
  376.       bcopy(remoteStopInfo.regs.ins,regs+4*8,4*8);
  377.       ((int *)regs)[Y_REGNUM] = remoteStopInfo.regs.y; 
  378.       ((int *)regs)[PS_REGNUM] = remoteStopInfo.regs.curPsr; 
  379.       ((int *)regs)[PC_REGNUM] = remoteStopInfo.regs.pc; 
  380.       ((int *)regs)[NPC_REGNUM] = remoteStopInfo.regs.nextPc; 
  381.       remote_read_bytes(remoteStopInfo.regs.ins[6], 
  382.             ((int *) regs) + FIRST_LOCAL_REGNUM,4*16);
  383.       return;
  384.   }
  385.   ERROR_NO_ATTACHED_HOST;
  386.   Kdbx_Trace(DBG_GET_STOP_INFO, (char *) 0, (char *)&stopInfo,
  387.                sizeof(stopInfo));
  388.   bcopy(stopInfo.regs.globals,regs,4*8);
  389.   bcopy(stopInfo.regs.ins,regs+4*8,4*8);
  390.   ((int *)regs)[Y_REGNUM] = stopInfo.regs.y; 
  391.   ((int *)regs)[PS_REGNUM] = stopInfo.regs.curPsr; 
  392.   ((int *)regs)[PC_REGNUM] = stopInfo.regs.pc; 
  393.   ((int *)regs)[NPC_REGNUM] = stopInfo.regs.nextPc; 
  394.   remote_read_bytes(stopInfo.regs.ins[6], 
  395.         ((int *) regs) + FIRST_LOCAL_REGNUM,4*16);
  396.  
  397. }
  398.  
  399.  
  400. int
  401. remote_attach(pid)
  402.     int    pid;
  403. {
  404.     int    status;
  405.     struct expression *expr;
  406.     register struct cleanup *old_chain;
  407.     register value val;
  408.     int    machRegStateAddr;
  409.     Proc_ControlBlock    *procPtr;
  410.     Mach_RegState machRegState;
  411.     char    exp[128];
  412.  
  413.     if (remoteCoreChan >= 0) {
  414.     if (pid != lastPid) {
  415.       /*
  416.        * Switching to a new process. 
  417.        */
  418.       if (pid == -1) {
  419.           /*
  420.            * Process -1 is the trap process. Whose stop info is 
  421.            * in the beginning of the corefile.
  422.            */
  423.           if (lseek(remoteCoreChan, 0, L_SET) < 0) {
  424.           error("lseek corefile");
  425.           return 0;
  426.            }
  427.           if (myread(remoteCoreChan, &remoteStopInfo, 
  428.             sizeof(remoteStopInfo)) < 0) {
  429.           error("read corefile");
  430.           return 0;
  431.           }
  432.           lastPid = pid;
  433.           start_remote();
  434.           return 1;
  435.       }
  436.       /*
  437.        * Lookup the switch regs of the specified process.
  438.        * They are in proc_PCBTable[pidSlot]->machStatePtr->switchRegs.
  439.        */
  440.       sprintf(exp,"proc_PCBTable[%d]", pid & 0xff);
  441.       expr = parse_c_expression (exp);
  442.       old_chain = make_cleanup (free_current_contents, &expr);
  443.  
  444.       val = evaluate_expression (expr);
  445.       do_cleanups (old_chain);
  446.       if ((value_as_long(val) == NIL) || (value_as_long(val) == 0)) {
  447.           error("Pid 0x%x does not have a control block\n", pid);
  448.       }
  449.       sprintf(exp,"proc_PCBTable[%d]->machStatePtr->switchRegs", pid & 0xff);
  450.       expr = parse_c_expression (exp);
  451.       old_chain = make_cleanup (free_current_contents, &expr);
  452.       val = evaluate_expression (expr);
  453.       do_cleanups (old_chain);
  454.       machRegStateAddr = value_as_long(val);
  455.       if (remote_read_bytes(machRegStateAddr, &machRegState, 
  456.             sizeof(Mach_RegState)) != 0) {
  457.         error("Can't read  regs from address 0x%x\n", machRegStateAddr);
  458.       }
  459.       remoteStopInfo.regs = machRegState;
  460.       /*
  461.        * The PC that is stored for a switch registers from on the
  462.        * sun4 is bogus.  We set the PC to be inside Mach_ContextSwitch.
  463.        */
  464.       strcpy(exp,"&Mach_ContextSwitch");
  465.       expr = parse_c_expression (exp);
  466.       old_chain = make_cleanup (free_current_contents, &expr);
  467.       val = evaluate_expression (expr);
  468.       do_cleanups (old_chain);
  469.       remoteStopInfo.regs.pc = value_as_long(val)+16;
  470.       remoteStopInfo.regs.nextPc = remoteStopInfo.regs.pc+4;
  471.       lastPid = pid;
  472.     }
  473.     start_remote();
  474.     return 1;
  475.     }
  476.     ERROR_NO_ATTACHED_HOST;
  477.     if (pid != lastPid) {
  478.     Kdbx_Trace(DBG_SET_PID, &pid, 0,sizeof(int));
  479.     lastPid = pid;
  480.     }
  481.     start_remote();
  482.     return 1;
  483. }
  484.  
  485. /* remote_detach()
  486.    takes a program previously attached to and detaches it.
  487.    We better not have left any breakpoints
  488.    in the program or it'll die when it hits one.
  489.    Close the open connection to the remote debugger.
  490.    Use this when you want to detach and do something else
  491.    with your gdb.  */
  492.  
  493. static void
  494. remote_detach(args, from_tty)
  495.      char *args;
  496.      int from_tty;
  497. {
  498.   int cur_pc;
  499.  
  500.   ERROR_NO_ATTACHED_HOST;
  501.   cur_pc = read_pc();
  502.   if (args) 
  503.       Kdbx_Trace(DBG_DETACH, &cur_pc, 0, sizeof(int));
  504.   remote_clean_up();
  505.   pop_target ();
  506.   if (from_tty)
  507.     printf ("Ending remote debugging.\n");
  508. }
  509.  
  510.  
  511.  
  512. /* Read a word from remote address ADDR and return it.
  513.    This goes through the data cache.  */
  514.  
  515. int
  516. remote_fetch_word (addr)
  517.      CORE_ADDR addr;
  518. {
  519.  
  520.   int buffer;
  521.   extern CORE_ADDR text_start, text_end;
  522.  
  523.   if (remoteCoreChan >= 0) {
  524.       if (IN_CORE_FILE(addr)) {
  525.       if (lseek(remoteCoreChan, addr - remoteOffset, L_SET) < 0) {
  526.           perror("lseek corefile");
  527.           errno = EIO;
  528.           return 0;
  529.        }
  530.       if (myread(remoteCoreChan, &buffer, sizeof(buffer)) < 0) {
  531.           perror("read corefile");
  532.           errno = EIO;
  533.           return 0;
  534.       }
  535.       } else {
  536.       /* fprintf(stderr, "Address 0x%x out of range\n", addr); */
  537.       errno = EIO;
  538.       return 0;
  539.       }
  540.       return buffer;
  541.   }
  542.  
  543.   ERROR_NO_ATTACHED_HOST;
  544.   if (addr >= text_start && addr < text_end)
  545.     {
  546.      if (Kdbx_Trace(DBG_INST_READ, addr, &buffer, sizeof(int)) != 0) {
  547.         errno = EIO;
  548.         return 0;
  549.      }
  550.      return buffer;
  551.     }
  552.   if (Kdbx_Trace(DBG_DATA_READ, addr, &buffer, sizeof(int)) != 0) {
  553.     errno = EIO;
  554.     return 0;
  555.   }
  556.   return buffer;
  557. }
  558.  
  559. /* Write a word WORD into remote address ADDR.
  560.    This goes through the data cache.  */
  561.  
  562. void
  563. remote_store_word (addr, word)
  564.      CORE_ADDR addr;
  565.      int word;
  566. {
  567.   extern CORE_ADDR text_start, text_end;
  568.   ERROR_NO_ATTACHED_HOST;
  569.   if (addr >= text_start && addr < text_end)
  570.     {
  571.       if (Kdbx_Trace(DBG_INST_WRITE, &word, addr, sizeof(word))!= 0) {
  572.         errno = EIO;
  573.         }
  574.         return;
  575.     }
  576.   if ( Kdbx_Trace(DBG_DATA_WRITE,  &word, addr, sizeof(word)) != 0) {
  577.      errno = EIO;
  578.   }
  579.   return;
  580. }
  581.  
  582. /* Write memory data directly to the remote machine.
  583.    This does not inform the data cache; the data cache uses this.
  584.    MEMADDR is the address in the remote memory space.
  585.    MYADDR is the address of the buffer in our space.
  586.    LEN is the number of bytes.  */
  587.  
  588. int
  589. remote_write_bytes (memaddr, myaddr, len)
  590.      CORE_ADDR memaddr;
  591.      char *myaddr;
  592.      int len;
  593. {
  594.   extern CORE_ADDR text_start, text_end;
  595.   ERROR_NO_ATTACHED_HOST;
  596.   if (memaddr >= text_start && memaddr < text_end)
  597.     {
  598.       return Kdbx_Trace(DBG_INST_WRITE, myaddr, memaddr, len);
  599.     }
  600.   return Kdbx_Trace(DBG_DATA_WRITE,  myaddr, memaddr, len);
  601. }
  602.  
  603. /* Read memory data directly from the remote machine.
  604.    This does not use the data cache; the data cache uses this.
  605.    MEMADDR is the address in the remote memory space.
  606.    MYADDR is the address of the buffer in our space.
  607.    LEN is the number of bytes.  */
  608.  
  609. int
  610. remote_read_bytes (memaddr, myaddr, len)
  611.      CORE_ADDR memaddr;
  612.      char *myaddr;
  613.      int len;
  614. {
  615.     int err;
  616.  
  617.   if (remoteCoreChan >= 0) {
  618.       if (IN_CORE_FILE(memaddr)) {
  619.       if (lseek(remoteCoreChan, memaddr - remoteOffset, L_SET) < 0) {
  620.           err = errno;
  621.           perror("lseek corefile");
  622.           return err;
  623.        }
  624.       if (myread(remoteCoreChan,myaddr, len) != len) {
  625.           err = errno;
  626.           perror("read corefile");
  627.           return (err > 0) ? err : 1;
  628.       }
  629.     } else {
  630.       /* fprintf(stderr, "Address 0x%x out of range\n", memaddr); */
  631.       return EIO;
  632.     }
  633.     return 0;
  634.   }
  635.   ERROR_NO_ATTACHED_HOST;
  636.   return Kdbx_Trace(DBG_DATA_READ, memaddr, myaddr, len);
  637. }
  638.  
  639. /* Read LEN bytes from inferior memory at MEMADDR.  Put the result
  640.    at debugger address MYADDR.  Returns errno value.  */
  641. int
  642. remote_read_inferior_memory(memaddr, myaddr, len)
  643.      CORE_ADDR memaddr;
  644.      char *myaddr;
  645.      int len;
  646. {
  647.   int xfersize, err;
  648.   while (len > 0)
  649.     {
  650.       if (len > MAXBUFBYTES)
  651.     xfersize = MAXBUFBYTES;
  652.       else
  653.     xfersize = len;
  654.  
  655.       err = remote_read_bytes (memaddr, myaddr, xfersize);
  656.       if (err != 0) 
  657.       return err;
  658.       memaddr += xfersize;
  659.       myaddr  += xfersize;
  660.       len     -= xfersize;
  661.     }
  662.   return 0; /* no error */
  663. }
  664.  
  665. /* Copy LEN bytes of data from debugger memory at MYADDR
  666.    to inferior's memory at MEMADDR.  Returns errno value.  */
  667. int
  668. remote_write_inferior_memory (memaddr, myaddr, len)
  669.      CORE_ADDR memaddr;
  670.      char *myaddr;
  671.      int len;
  672. {
  673.   int xfersize;
  674.   int err;
  675.   while (len > 0)
  676.     {
  677.       if (len > MAXBUFBYTES)
  678.     xfersize = MAXBUFBYTES;
  679.       else
  680.     xfersize = len;
  681.  
  682.       err = remote_write_bytes(memaddr, myaddr, xfersize);
  683.       if (err != 0) {
  684.     return err;
  685.       }
  686.  
  687.       memaddr += xfersize;
  688.       myaddr  += xfersize;
  689.       len     -= xfersize;
  690.     }
  691.   return 0; /* no error */
  692. }
  693.  
  694. /* Store the remote registers from the contents of the block REGS.  */
  695.  
  696. void
  697. remote_store_registers (regs,regno)
  698.      char *regs;
  699.      int    regno;
  700. {
  701.     int    i;
  702.  
  703.   ERROR_NO_ATTACHED_HOST;
  704.     if (regno < 0) { 
  705.     remote_write_bytes(((int *) regs)[SP_REGNUM], 
  706.                 ((int *) regs) + FIRST_LOCAL_REGNUM,4*16);
  707.     for (i = 0; i < 16; i++) {
  708.         Kdbx_Trace(DBG_WRITE_REG, &(((int *)regs)[i]),
  709.                     Regnum_to_index(i),sizeof(int));
  710.     }    
  711.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+Y_REGNUM,
  712.             Regnum_to_index(Y_REGNUM),sizeof(int));
  713.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+PC_REGNUM,
  714.             Regnum_to_index(PC_REGNUM),sizeof(int));
  715.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+NPC_REGNUM,
  716.             Regnum_to_index(NPC_REGNUM),sizeof(int));
  717.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+PS_REGNUM,
  718.             Regnum_to_index(PS_REGNUM),sizeof(int));
  719.  
  720.     } else {
  721.        int    ind = Regnum_to_index(regno);
  722.        if (ind >= 0) 
  723.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+regno,ind,sizeof(int));
  724.        else
  725.         remote_write_bytes(((int *) regs)[SP_REGNUM], 
  726.             ((int *) regs) + regno,4);
  727.     }
  728. }
  729.  
  730. /* 
  731.  * Call a remote function.
  732.  */
  733. call_remote_function(funaddr,nargs,numBytes,argBuffer)
  734.     CORE_ADDR funaddr;
  735.     int        nargs;
  736.     int        numBytes;
  737.     char    *argBuffer;
  738. {
  739.   int    returnValue;
  740.   ERROR_NO_ATTACHED_HOST;
  741.   Kdbx_Trace(DBG_BEGIN_CALL, (char *)0, (char *)0, 0);  
  742.   returnValue = Kdbx_Trace(DBG_CALL_FUNCTION,argBuffer,funaddr,numBytes);
  743.   Kdbx_Trace(DBG_END_CALL, (char *)0, (char *)0, 0);       
  744.   return returnValue;
  745. }
  746.  
  747. void
  748. remote_reboot (args)
  749.      char *args;
  750. {
  751.  
  752.   ERROR_NO_ATTACHED_HOST;
  753.   if (!args)
  754.     args = "";
  755.  
  756.   Kdbx_Trace(DBG_REBOOT, args, NULL, strlen(args));
  757. }
  758.  
  759.  
  760. #include <sys/types.h>
  761. #include <sys/socket.h>
  762. #include <sys/time.h>
  763. #include <netinet/in.h>
  764. #include <netdb.h>
  765. #include <sgtty.h>
  766.  
  767. /*
  768.  * Direct mapped cache of data and code.   The cache is flushed after every
  769.  * step and continue by incrementing the version number.  Flushing code
  770.  * isn't necessary but since kdbx already has an internal code cache it
  771.  * doesn't hurt and makes life easier.
  772.  */
  773. static    int    cacheBlockSize = -1;
  774. static    int    cacheBlockShift = -1;
  775. static    int    cacheSize = 128 * 1024;
  776. #define    CACHE_BLOCK_MASK     (cacheSize / cacheBlockSize - 1)
  777. #define    CACHE_BLOCK_OFFSET_MASK    (cacheBlockSize - 1)
  778. #define    NUM_CACHE_BLOCKS    (cacheSize >> cacheBlockShift)
  779. #define    CACHE_OFFSET_MASK    (cacheSize - 1)
  780. #define    GET_CACHE_BLOCK(address) (((unsigned int) address) >> cacheBlockShift)
  781. /*
  782.  * The data cache is just an array of characters.
  783.  */
  784. static    char    *dataCache;
  785. /*
  786.  * There is information about kept about each cache block.
  787.  */
  788. typedef    struct {
  789.     int        version;    /* Version number of this cache block. */
  790.     char    *realAddr;    /* Actual address of data stored in the block.*/
  791. } CacheInfo;
  792. static CacheInfo    *cacheInfo;
  793. static int    currentVersion = 1;
  794.  
  795. /*
  796.  * Stuff for the serial port.
  797.  */
  798. static    int    kernChannel = 0;
  799.  
  800.  
  801. /*
  802.  * Message buffers.
  803.  */
  804. static Dbg_Msg    msg;
  805. static int    msgSize;
  806. #define    REPLY_BUFFER_SIZE    16384
  807. static    char    replyBuffer[REPLY_BUFFER_SIZE];
  808. static    char    requestBuffer[DBG_MAX_REQUEST_SIZE];
  809. static    int    msgNum = 0;
  810.  
  811. static void    RecvReply();
  812.  
  813. static    struct sockaddr_in    remote;
  814. static    int            kdbxTimeout = 1;
  815. static    int            netSocket;
  816.  
  817.  
  818. /*
  819.  *----------------------------------------------------------------------
  820.  *
  821.  * CreateSocket --
  822.  *
  823.  *    Creates a UDP socket connected to the Sprite host's kernel 
  824.  *    debugger port.
  825.  *
  826.  * Results:
  827.  *    The stream ID of the socket.
  828.  *
  829.  * Side effects:
  830.  *    None.
  831.  *
  832.  *----------------------------------------------------------------------
  833.  */
  834. static int
  835. CreateSocket(spriteHostName)
  836.     char    *spriteHostName;
  837. {
  838.     int            socketID;
  839.     struct hostent     *hostPtr;
  840.  
  841.     hostPtr = gethostbyname(spriteHostName);
  842.     if (hostPtr == (struct hostent *) NULL) {
  843.     error("CreateSocket: unknown host %s\n", spriteHostName);
  844.     }
  845.     if (hostPtr->h_addrtype != AF_INET) {
  846.     error("CreateSocket: bad address type for host %s\n", 
  847.         spriteHostName);
  848.     }
  849.  
  850.     socketID = socket(AF_INET, SOCK_DGRAM, 0);
  851.     if (socketID < 0) {
  852.     perror_with_name("CreateSocket: socket");
  853.     }
  854.  
  855.     bzero((Address)&remote, sizeof(remote));
  856.     bcopy(hostPtr->h_addr, (Address)&remote.sin_addr, hostPtr->h_length);
  857.     remote.sin_port = htons(DBG_UDP_PORT);
  858.     remote.sin_family = AF_INET;
  859.  
  860.     if (connect(socketID, (struct sockaddr *) &remote, sizeof(remote)) < 0) {
  861.     perror_with_name("CreateSocket: connect");
  862.     }
  863.  
  864.     return(socketID);
  865. }
  866.  
  867.  
  868. /*
  869.  * ----------------------------------------------------------------------------
  870.  *
  871.  *  StartDebugger --
  872.  *
  873.  *     Start off a new conversation with the debugger.
  874.  *
  875.  * Results:
  876.  *     None.
  877.  *
  878.  * Side effects:
  879.  *     Setup r network socket.
  880.  * ----------------------------------------------------------------------------
  881.  */
  882. static void
  883. StartDebugger()
  884. {
  885.         char    *host = hostName;
  886.     hostName = (char *) 0;
  887.     netSocket = CreateSocket(host);
  888.     hostName = host;
  889. }
  890.  
  891.  
  892. /*
  893.  * ----------------------------------------------------------------------------
  894.  *
  895.  *  SendRequest --
  896.  *
  897.  *     Send a request message to the kernel.
  898.  *
  899.  * Results:
  900.  *     None.
  901.  *
  902.  * Side effects:
  903.  *     None.
  904.  * ----------------------------------------------------------------------------
  905.  */
  906. static void
  907. SendRequest(numBytes, newRequest)
  908.     int        numBytes;
  909.     Boolean    newRequest;
  910. {
  911.      {
  912.     Dbg_Opcode    opcode;
  913.  
  914.     msgSize = numBytes;
  915.     if (newRequest) {
  916.         msgNum++;
  917.     }
  918.     *(int *)requestBuffer = msgNum;
  919.     bcopy(&msg, requestBuffer + 4, numBytes);
  920.     if (write(netSocket, requestBuffer, numBytes + 4) < numBytes + 4) {
  921.          MARK_DISCONNECTED;
  922.         perror_with_name("SendRequest: Couldn't write to the kernel socket\n");
  923.         return;
  924.     }
  925.     if (newRequest) {
  926.         opcode = (Dbg_Opcode) msg.opcode;
  927.         if (opcode == DBG_DETACH || opcode == DBG_CONTINUE ||
  928.         opcode == DBG_SINGLESTEP || opcode == DBG_DIVERT_SYSLOG || 
  929.         opcode == DBG_BEGIN_CALL || 
  930.         opcode == DBG_WRITE_REG || opcode == DBG_SET_PID) {
  931.         int    dummy;
  932.         /*
  933.          * Wait for explicit acknowledgments of these packets.
  934.          */
  935.         RecvReply(opcode, 4, &dummy, NULL, 1);
  936.         }
  937.     }
  938.     }
  939. }
  940.  
  941.  
  942. /*
  943.  * ----------------------------------------------------------------------------
  944.  *
  945.  *  RecvReply --
  946.  *
  947.  *     Receive a reply from the kernel.
  948.  *
  949.  * Results:
  950.  *     None.
  951.  *
  952.  * Side effects:
  953.  *     None.
  954.  * ----------------------------------------------------------------------------
  955.  */
  956. static void
  957. RecvReply(opcode, numBytes, destAddr, readStatusPtr, timeout)
  958.     Dbg_Opcode    opcode;
  959.     int        numBytes;
  960.     char    *destAddr;
  961.     int    *readStatusPtr;
  962.     int    timeout;
  963. {
  964.     int        status;
  965.     int     resendRequest = 0;
  966.  
  967.     if (numBytes + 8 > REPLY_BUFFER_SIZE) {
  968.     fprintf(stderr,"numBytes <%d> > REPLY_BUFFER_SIZE <%d>\n",
  969.             numBytes + 8, REPLY_BUFFER_SIZE);
  970.     abort();
  971.     }
  972.      {
  973.     int        readMask;
  974.     struct    timeval    interval;
  975.     int        bytesRead;
  976.  
  977.     interval.tv_sec = kdbxTimeout;
  978.     interval.tv_usec = 0;
  979.     do {
  980.         if (timeout) {
  981.         int    numTimeouts;
  982.  
  983.         numTimeouts = 0;
  984.         /*
  985.          * Loop timing out and sending packets until a new packet
  986.          * has arrived.
  987.          */
  988.         do {
  989.             if (!resendRequest) { 
  990.             readMask = 1 << netSocket;
  991.             status = select(32, &readMask, NULL, NULL, &interval);
  992.             } else {
  993.             status = 0;
  994.             resendRequest = 0;
  995.             }
  996.             if (status == 1) {
  997.             break;
  998.             } else if (status == -1) {
  999.                 MARK_DISCONNECTED;
  1000.             perror_with_name("RecvReply: Couldn't select on socket.\n");
  1001.             } else if (status == 0) {
  1002.             SendRequest(msgSize, 0);
  1003.             numTimeouts++;
  1004.             if (numTimeouts % 10 == 0) {
  1005.                 fprintf(stderr, 
  1006.                     "Timing out and resending to host %s\n",
  1007.                     hostName);
  1008.                 fflush(stderr);
  1009.                 QUIT;
  1010.             }
  1011.             }
  1012.         } while (1);
  1013.         }
  1014.         if (opcode == DBG_DATA_READ || opcode == DBG_INST_READ ||
  1015.         opcode == DBG_GET_VERSION_STRING) {
  1016.         /*
  1017.          * Data and instruction reads return variable size packets.
  1018.          * The first two ints are message number and status.  If
  1019.          * the status is OK then the data follows.
  1020.          */
  1021.         immediate_quit++;
  1022.         bytesRead = read(netSocket, replyBuffer, numBytes + 8);
  1023.         immediate_quit--;
  1024.         if (bytesRead < 0) {
  1025.             MARK_DISCONNECTED;
  1026.             perror_with_name("RecvReply: Error reading socket.");
  1027.         }
  1028.         /*
  1029.          * Check message number before the size because this could
  1030.          * be an old packet.
  1031.          */
  1032.         if (*(int *)replyBuffer != msgNum) {
  1033.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1034.                 *(int *)replyBuffer, msgNum);
  1035.             fflush(stdout);
  1036.             resendRequest = 1;
  1037.             continue;
  1038.         }
  1039.         if (bytesRead == 8) {
  1040.             /*
  1041.              * Only 8 bytes so the read failed and there is no data.
  1042.              */
  1043.             *readStatusPtr = 0;
  1044.             return;
  1045.         }
  1046.             if (opcode == DBG_GET_VERSION_STRING) {
  1047.              strncpy(destAddr, (char *)(replyBuffer + 4),numBytes);
  1048.              return;
  1049.         }
  1050.         if (bytesRead != numBytes + 8) {
  1051.             printf("RecvReply: Short read (1): op=%d exp=%d read=%d",
  1052.                 opcode, numBytes + 4, bytesRead);
  1053.             continue;
  1054.         }
  1055.         *readStatusPtr = 1;
  1056.         bcopy(replyBuffer + 8, destAddr, numBytes);
  1057.         return;
  1058.         } else if (opcode == DBG_END_CALL) {
  1059.         int    length;
  1060.         /*
  1061.          * End call returns a variable size packet that contains
  1062.          * the result of the call. The format of the message is 
  1063.          * message number, length, data.
  1064.          */
  1065.         immediate_quit++;
  1066.         bytesRead = read(netSocket, replyBuffer, REPLY_BUFFER_SIZE);
  1067.         immediate_quit--;
  1068.         if (bytesRead < 0) {
  1069.             MARK_DISCONNECTED;
  1070.             perror_with_name("RecvReply: Error reading socket.");
  1071.         }
  1072.         /*
  1073.          * Check message number before the size because this could
  1074.          * be an old packet.
  1075.          */
  1076.         if (*(int *)replyBuffer != msgNum) {
  1077.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1078.                 *(int *)replyBuffer, msgNum);
  1079.             fflush(stdout);
  1080.             resendRequest = 1;
  1081.             continue;
  1082.         }
  1083.         length = *( int *)(replyBuffer + 4);
  1084.         if (bytesRead - 8 != length) {
  1085.             fprintf(stderr, "RecyReply: Short read for syslog data\n");
  1086.             fflush(stderr);
  1087.             length = bytesRead - 8;
  1088.         }
  1089.         if (length == 0) {
  1090.             /*
  1091.              * No data.
  1092.              */
  1093.             *readStatusPtr = 0;
  1094.             return;
  1095.         }
  1096.         /*
  1097.          * Dump out the buffer.
  1098.          */
  1099.         write(1, replyBuffer + 8, length);
  1100.         *readStatusPtr = 1;
  1101.         return;
  1102.         } else {
  1103.         /*
  1104.          * Normal request so just read in the message which includes
  1105.          * the message number.
  1106.          */
  1107.         immediate_quit++;
  1108.         bytesRead = read(netSocket, replyBuffer, numBytes + 4);
  1109.         immediate_quit--;
  1110.         if (bytesRead < 0) {
  1111.             MARK_DISCONNECTED;
  1112.             perror_with_name("RecvReply: Error reading socket (2).");
  1113.         }
  1114.         /*
  1115.          * Check message number before size because it could be
  1116.          * an old packet.
  1117.          */
  1118.         if (*(int *)replyBuffer != msgNum) {
  1119.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1120.                 *(int *)replyBuffer, msgNum);
  1121.             fflush(stdout);
  1122.             resendRequest = 1;
  1123.             continue;
  1124.         }
  1125.         if (bytesRead != numBytes + 4) {
  1126.             printf("RecvReply: Short read (2): op=%d exp=%d read=%d",
  1127.                 opcode, numBytes + 4, bytesRead);
  1128.         }
  1129.         if (*(int *)replyBuffer != msgNum) {
  1130.             continue;
  1131.         }
  1132.         bcopy(replyBuffer + 4, destAddr, numBytes);
  1133.         return;
  1134.         }
  1135.     } while (1);
  1136.     }
  1137. }
  1138.  
  1139.  
  1140. /*
  1141.  * ----------------------------------------------------------------------------
  1142.  *
  1143.  *  WaitForKernel --
  1144.  *
  1145.  *      Wait for the kernel to send us a message to indicate that it is waiting
  1146.  *    to be debugged.
  1147.  *
  1148.  * Results:
  1149.  *     None.
  1150.  *
  1151.  * Side effects:
  1152.  *     None.
  1153.  * ----------------------------------------------------------------------------
  1154.  */
  1155. static void
  1156. WaitForKernel()
  1157. {
  1158.     int    dummy;
  1159.  
  1160.     RecvReply(DBG_CONTINUE, 4, &dummy, NULL, 0);
  1161. }
  1162.  
  1163.  
  1164. /*
  1165.  * ----------------------------------------------------------------------------
  1166.  *
  1167.  * BlockInCache --
  1168.  *
  1169.  *     See if the given block at the given address is in the cache.
  1170.  *
  1171.  * Results:
  1172.  *     1 if found block in cache, 0 if didn't.
  1173.  *
  1174.  * Side effects:
  1175.  *     None.
  1176.  */
  1177. static int
  1178. BlockInCache(blockNum, addr)
  1179.     int        blockNum;
  1180.     char    *addr;
  1181. {
  1182.     blockNum = blockNum & CACHE_BLOCK_MASK;
  1183.     return((int) (cacheInfo[blockNum].version == currentVersion &&
  1184.        (unsigned int) cacheInfo[blockNum].realAddr == 
  1185.             ((unsigned int) (addr) & ~CACHE_BLOCK_OFFSET_MASK)));
  1186. }
  1187.  
  1188.  
  1189. /*
  1190.  * ----------------------------------------------------------------------------
  1191.  *
  1192.  * FetchBlock --
  1193.  *
  1194.  *     Fetch the given data block from the cache or the kernel if necessary.
  1195.  *
  1196.  * Results:
  1197.  *     1 if could fetch block into cache, 0 if couldn't.
  1198.  *
  1199.  * Side effects:
  1200.  *     Data cache modified.
  1201.  */
  1202. static int
  1203. FetchBlock(blockNum, srcAddr, opcode)
  1204.     int        blockNum;
  1205.     char    *srcAddr;
  1206.     Dbg_Opcode    opcode;
  1207. {
  1208.     int    successfulRead;
  1209.  
  1210.     blockNum = blockNum & CACHE_BLOCK_MASK;
  1211.     srcAddr = (char *) ((unsigned int) (srcAddr) & ~CACHE_BLOCK_OFFSET_MASK);
  1212.  
  1213.     if (BlockInCache(blockNum, srcAddr)) {
  1214.     return(1);
  1215.     }
  1216.     msg.opcode = opcode;
  1217.     msg.data.readMem.address = (int) srcAddr;
  1218.     msg.data.readMem.numBytes = cacheBlockSize;
  1219.     SendRequest(sizeof(msg.opcode) + sizeof(Dbg_ReadMem), 1);
  1220.     RecvReply(opcode, cacheBlockSize, 
  1221.         &dataCache[(unsigned int) (srcAddr) & CACHE_OFFSET_MASK],
  1222.         &successfulRead, 1);
  1223.     if (successfulRead) {
  1224.     cacheInfo[blockNum].version = currentVersion;
  1225.     cacheInfo[blockNum].realAddr = srcAddr;
  1226.     }
  1227.     return(successfulRead);
  1228. }
  1229.  
  1230.  
  1231.  
  1232. /*
  1233.  * ----------------------------------------------------------------------------
  1234.  *
  1235.  * Kdbx_Trace --
  1236.  *
  1237.  *     Write the trace command over to the kernel.  
  1238.  *
  1239.  * Results:
  1240.  *     None.
  1241.  *
  1242.  * Side effects:
  1243.  *     None.
  1244.  *
  1245.  * ----------------------------------------------------------------------------
  1246.  */
  1247. int 
  1248. Kdbx_Trace(opcode, srcAddr, destAddr, numBytes)
  1249.     Dbg_Opcode    opcode;        /* Which command */
  1250.     char    *srcAddr;    /* Where to read data from */
  1251.     char    *destAddr;    /* Where to write data to */
  1252.     int        numBytes;    /* The number of bytes to read or write */
  1253. {
  1254.     int            (*intrHandler)();
  1255.     int            i;
  1256.     int            retVal = 0;
  1257.  
  1258.     if (!initialized) {
  1259.     int    moreData;
  1260.     /*
  1261.      * Setup the cache and initiate a conversation with the other kernel.
  1262.      */
  1263.     if (cacheBlockSize == -1) {
  1264.          {
  1265.         cacheBlockSize = 256;
  1266.         cacheBlockShift = 8;
  1267.         }
  1268.     }
  1269.     dataCache = (char *) malloc(cacheSize);
  1270.     cacheInfo = (CacheInfo *) malloc(NUM_CACHE_BLOCKS * sizeof(CacheInfo));
  1271.     for (i = 0; i < NUM_CACHE_BLOCKS; i++) {
  1272.         cacheInfo[i].version = 0;
  1273.     }
  1274.     StartDebugger();
  1275.     /*
  1276.      * Dump the system log by faking a call command.
  1277.      */
  1278.     printf("Dumping system log ...\n");
  1279.     fflush(stdout);
  1280.     msg.opcode = (short)DBG_BEGIN_CALL;
  1281.     SendRequest(sizeof(msg.opcode), 1);
  1282.     msg.opcode = (short)DBG_END_CALL;
  1283.     do {
  1284.         SendRequest(sizeof(msg.opcode), 1);
  1285.         RecvReply(msg.opcode, 0, NULL, &moreData, 1);
  1286.     } while (moreData);
  1287.     initialized = 1;
  1288.     }
  1289.  
  1290.  
  1291.     if (opcode == DBG_DATA_READ || opcode == DBG_INST_READ) {
  1292.     int            firstBlock;
  1293.     int            lastBlock;
  1294.     unsigned    int    cacheOffset;
  1295.     int            toRead;
  1296.  
  1297.     /*
  1298.      * Read using the cache.
  1299.      */
  1300.     firstBlock = GET_CACHE_BLOCK(srcAddr); 
  1301.     lastBlock = GET_CACHE_BLOCK(srcAddr + numBytes - 1);
  1302.     for (i = firstBlock; i <= lastBlock; i++) {
  1303.         cacheOffset = ((unsigned int) srcAddr) & CACHE_OFFSET_MASK;
  1304.         if (i == lastBlock) {
  1305.         toRead = numBytes;
  1306.         } else if (i == firstBlock) {
  1307.         toRead = cacheBlockSize - 
  1308.                 (cacheOffset & CACHE_BLOCK_OFFSET_MASK);
  1309.         } else {
  1310.         toRead = cacheBlockSize;
  1311.         }
  1312.         if (!FetchBlock(i, srcAddr, opcode)) {
  1313.         return EIO;
  1314.         }
  1315.         bcopy(&dataCache[cacheOffset], destAddr, toRead);
  1316.         srcAddr += toRead;
  1317.         destAddr += toRead;
  1318.         numBytes -= toRead;
  1319.     }
  1320.     return(0);
  1321.     }
  1322.  
  1323.     if (opcode == DBG_DATA_WRITE || opcode == DBG_INST_WRITE) {
  1324.     int    firstBlock;
  1325.     int    lastBlock;
  1326.     int    cacheOffset;
  1327.     int    toWrite;
  1328.     char    *tSrcAddr;
  1329.     char    *tDestAddr;
  1330.     int    tNumBytes;
  1331.  
  1332.     /*
  1333.      * If the block that is being fetched is in the cache then write the
  1334.      * data there first before sending it over to the kernel.
  1335.      */
  1336.     tSrcAddr = srcAddr;
  1337.     tDestAddr = destAddr;
  1338.     tNumBytes = numBytes;
  1339.  
  1340.     firstBlock = GET_CACHE_BLOCK(destAddr); 
  1341.     lastBlock = GET_CACHE_BLOCK(destAddr + numBytes - 1);
  1342.     for (i = firstBlock; i <= lastBlock; i++) {
  1343.         cacheOffset = ((int) tDestAddr) & CACHE_OFFSET_MASK;
  1344.         if (i == lastBlock) {
  1345.         toWrite = tNumBytes;
  1346.         } else if (i == firstBlock) {
  1347.         toWrite = cacheBlockSize - 
  1348.                 (cacheOffset & CACHE_BLOCK_OFFSET_MASK);
  1349.         } else {
  1350.         toWrite = cacheBlockSize;
  1351.         }
  1352.         if (BlockInCache(i, tDestAddr)) {
  1353.         bcopy(tSrcAddr, &dataCache[cacheOffset], tNumBytes);
  1354.         }
  1355.         tSrcAddr += toWrite;
  1356.         tDestAddr += toWrite;
  1357.         tNumBytes -= toWrite;
  1358.     }
  1359.     }
  1360.  
  1361.     msg.opcode = (short) opcode;
  1362.  
  1363.     /*
  1364.      * Do the rest of the work for the desired operation.
  1365.      */
  1366.  
  1367.     switch (opcode) {
  1368.  
  1369.     /*
  1370.      * For these operations the desired data is read from the other
  1371.      * kernel and stored at destAddr.
  1372.      */
  1373.     case DBG_READ_ALL_REGS:
  1374.     case DBG_GET_STOP_INFO:
  1375.         SendRequest(sizeof(msg.opcode), 1);
  1376.         RecvReply(opcode, numBytes, destAddr, NULL, 1);
  1377.         break;
  1378.  
  1379.     /*
  1380.      * For this operation the desired data is read from srcAddr
  1381.      * and written to the other kernel.
  1382.      */
  1383.     case DBG_SET_PID:
  1384.         msg.data.pid = *(int *)srcAddr;
  1385.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pid), 1);
  1386.         break;
  1387.  
  1388.     /*
  1389.      * When writing a general purpose register first the address to write
  1390.      * that is stored in destAddr must be given to the other kernel.
  1391.      * Then the data itself which is stored at srcAddr can be written over.
  1392.      */
  1393.     case DBG_WRITE_REG:
  1394.         msg.data.writeReg.regNum = (int) destAddr;
  1395.         msg.data.writeReg.regVal = *(int *) srcAddr;
  1396.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_WriteReg), 1);
  1397.         break;
  1398.  
  1399.     /*
  1400.      * When writing to the kernels instruction or data space first the
  1401.      * address of where to write to (destAddr) and then the number of
  1402.      * bytes to write (numBytes) must be sent over.  Finally all of
  1403.      * the data is read from srcAddr and written over.
  1404.      */
  1405.  
  1406.     case DBG_INST_WRITE:
  1407.     case DBG_DATA_WRITE: {
  1408.         char    writeStatus;
  1409.  
  1410.         msg.data.writeMem.address = (int) destAddr;
  1411.         msg.data.writeMem.numBytes = numBytes;
  1412.         bcopy(srcAddr, msg.data.writeMem.buffer, numBytes);
  1413.         SendRequest(sizeof(msg.opcode) + 2 * sizeof(int) + numBytes, 1);
  1414.         RecvReply(opcode, 1, &writeStatus, NULL, 1);
  1415.         if (writeStatus == 0) {
  1416.         retVal = EIO;
  1417.         fprintf(stderr, "ERROR: invalid write address 0x%x\n",destAddr);
  1418.         } 
  1419.         break;
  1420.     }
  1421.     case DBG_DIVERT_SYSLOG:
  1422.         msg.data.syslogCmd = (Dbg_SyslogCmd)srcAddr;
  1423.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_SyslogCmd), 1);
  1424.         break;
  1425.     case DBG_BEGIN_CALL:
  1426.         SendRequest(sizeof(msg.opcode), 1);
  1427.         break;
  1428.     case DBG_END_CALL: {
  1429.         Boolean    moreData;
  1430.         do {
  1431.         SendRequest(sizeof(msg.opcode), 1);
  1432.         RecvReply(opcode, 0, NULL, &moreData, 1);
  1433.         } while (moreData);
  1434.         break;
  1435.     }
  1436.  
  1437.     case DBG_DETACH: {
  1438.         msg.opcode = (short) DBG_DIVERT_SYSLOG;
  1439.         msg.data.syslogCmd = DBG_SYSLOG_TO_ORIG;
  1440.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_SyslogCmd), 1);
  1441.  
  1442.         msg.opcode = (short) DBG_DETACH;
  1443.         msg.data.pc = *(int *) srcAddr;
  1444.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pc), 1);
  1445.         break;
  1446.     }
  1447.  
  1448.     case DBG_CONTINUE:
  1449.     case DBG_SINGLESTEP:
  1450.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pc), 1);
  1451.         currentVersion++;
  1452.         WaitForKernel();
  1453.         break;
  1454.  
  1455.     case DBG_CALL_FUNCTION: {
  1456.         int        returnValue;
  1457.  
  1458.         msg.data.callFunc.address = (int) destAddr;
  1459.         msg.data.callFunc.numBytes = numBytes;
  1460.         bcopy(srcAddr, msg.data.callFunc.buffer, numBytes);
  1461.         SendRequest(sizeof(msg.opcode) + 2 * sizeof(int) + numBytes, 1);
  1462.         RecvReply(opcode, sizeof(returnValue), &returnValue, NULL, 1);
  1463.         return (returnValue);
  1464.     }
  1465.     case DBG_REBOOT: {
  1466.         msg.data.reboot.stringLength = numBytes;
  1467.         bcopy(srcAddr, msg.data.reboot.string, numBytes);
  1468.         SendRequest(sizeof(msg.opcode) + sizeof(int) + numBytes, 1);
  1469.         return (0);
  1470.     }
  1471.     case DBG_GET_VERSION_STRING: {
  1472.         SendRequest(sizeof(msg.opcode), 1);
  1473.         RecvReply(opcode,numBytes , destAddr, NULL, 1);
  1474.         return (0);
  1475.     }
  1476.     default:
  1477.         printf("Unknown opcode %d\n", opcode);
  1478.         return(-1);
  1479.     }
  1480.     return(retVal);
  1481. }
  1482. remote_close()
  1483. {
  1484. }
  1485. remote_clean_up()
  1486. {
  1487.     MARK_DISCONNECTED;
  1488. }
  1489.  
  1490.  
  1491. read_kmem(memaddr, myaddr, len)
  1492.     char *memaddr;
  1493.     char *myaddr;
  1494.     int      len;
  1495. {
  1496.     static int fd = -1;
  1497.     int count;
  1498.  
  1499.     if (fd < 0) { 
  1500.     char template[100];
  1501.     /*
  1502.      * Open a temp file to write counters to. We unlink the file so it will
  1503.      * disappear when we exit.
  1504.      */
  1505.     strcpy(template, "/tmp/kgdbXXXXXXXX");
  1506.     fd = mkstemp(template);
  1507.     if (fd < 0) {
  1508.         error("open kmem tmp file");
  1509.     }
  1510.     (void) unlink(template);
  1511.     }
  1512.     if (lseek(fd, 0, L_SET) < 0) {
  1513.     error("lseek kmem file");
  1514.     }
  1515.     count = write(fd, memaddr, len);
  1516.     if (count != len) {
  1517.     return EIO;
  1518.     }
  1519.  
  1520.     /*
  1521.      * Rewind the file and read the counters from it.
  1522.      */
  1523.     count = lseek(fd, 0, L_SET);
  1524.     if (count >= 0) {
  1525.         count = read(fd, myaddr, len);
  1526.     }
  1527.     if (count != len) {
  1528.     return EIO;
  1529.     }
  1530.     return 0;
  1531. }
  1532.  
  1533.  
  1534.